package com.meshnetics.gb.stack.mac.primitives;

import com.meshnetics.gb.stack.core.event.StackEventType;
import com.meshnetics.gb.stack.core.event.StackResponse;
import com.meshnetics.gb.stack.mac.RadioMACStackLayer;
import com.meshnetics.gb.stack.mac.type.AssociationStatus;
import com.meshnetics.gb.type.impl.ByteUtils;
import com.meshnetics.gb.type.impl.zcl.Bool;
import com.meshnetics.gb.type.impl.zcl.TypeBool;
import com.meshnetics.gb.type.impl.zcl.TypeUInt;
import com.meshnetics.gb.type.impl.zcl.UInt;

import java.nio.ByteBuffer;

/**
 * WRITE DESCRIPTION HERE
 *
 * @author AKovylin
 */
public class MACAssociateResponse extends StackResponse implements MACCommand, MACReplyAwaited {
    public static final byte CODE = 0x48;

    private final UInt deviceAddress;
    private final UInt assocShortAddr;
    private final AssociationStatus assocStatus;
    private final Bool securityEnable;

    public MACAssociateResponse(long deviceAddress, short assocShortAddr, AssociationStatus assocStatus,
                                boolean securityEnable) {
        this(new Long(deviceAddress), new Short(assocShortAddr), assocStatus, Boolean.valueOf(securityEnable));
    }

    public MACAssociateResponse(Long deviceAddress, Short assocShortAddr, AssociationStatus assocStatus,
                                Boolean securityEnable) {
        this((UInt) TypeUInt.UINT_64.fromObject(deviceAddress), (UInt) TypeUInt.UINT_16.fromObject(assocShortAddr),
                assocStatus, (Bool) TypeBool.BOOLEAN.fromObject(securityEnable));
    }

    public MACAssociateResponse(UInt deviceAddress, UInt assocShortAddr, AssociationStatus assocStatus,
                                Bool securityEnable) {
        super("macAssociateResponse", StackEventType.LME_TYPE);
        if (deviceAddress == null) {
            throw new NullPointerException("deviceAddress is null");
        }
        if (assocShortAddr == null) {
            throw new NullPointerException("assocShortAddr is null");
        }
        if (assocStatus == null) {
            throw new NullPointerException("assocStatus is null");
        }
        if (securityEnable == null) {
            throw new NullPointerException("securityEnable is null");
        }
        if (securityEnable.isInvalid()) {
            throw new IllegalArgumentException("invalid securityEnable");
        }
        this.deviceAddress = deviceAddress.convert(TypeUInt.UINT_64);
        this.assocShortAddr = assocShortAddr.convert(TypeUInt.UINT_16);
        this.assocStatus = assocStatus;
        this.securityEnable = securityEnable;
    }

    public UInt getDeviceAddressType() {
        return deviceAddress;
    }

    public UInt getAssocShortAddrType() {
        return assocShortAddr;
    }

    public Long getDeviceAddress() {
        return (Long) deviceAddress.toObject();
    }

    public Short getAssocShortAddr() {
        return (Short) assocShortAddr.toObject();
    }

    public AssociationStatus getAssocStatus() {
        return assocStatus;
    }

    public Bool getSecurityEnableType() {
        return securityEnable;
    }

    public Boolean getSecurityEnable() {
        return (Boolean) securityEnable.toObject();
    }

    public byte getCode() {
        return CODE;
    }

    public int getSize(RadioMACStackLayer layer) {
        return 12;
    }

    public void serialize(ByteBuffer bb, RadioMACStackLayer layer) {
        ByteUtils.ensureNotNull(bb);
        deviceAddress.serialize(bb);
        assocShortAddr.serialize(bb);
        assocStatus.serialize(bb);
        securityEnable.serialize(bb);
    }

    public String toString() {
        return getName() + '(' + deviceAddress + ',' + assocShortAddr + ',' + assocStatus + ',' + securityEnable + ')';
    }
}
